using System.Diagnostics;
using System.Linq;
using HtmlAgilityPack;

internal class HtmlNodesReader
{
    private readonly HtmlNodeCollection nodes;
    private int index;
    private const string DivTag = "div";
    private const string H4Tag = "h4";
    private const string H3Tag = "h3";
    private const string H2Tag = "h2";
    private const string PreTag = "pre";
    private const string ATag = "a";
    private const string PTag = "p";
    private const string UlTag = "ul";
    private const string LiTag = "li";
    private const string SpanTag = "span";

    public HtmlNodesReader(HtmlNode node)
    {
        nodes = node.ChildNodes;
    }

    public HtmlNode Div
    {
        get
        {
            var result = nodes[index++];
            Debug.Assert(result.NodeType == HtmlNodeType.Element);
            Debug.Assert(result.Name == DivTag);
            return result;
        }
    }

    public HtmlNode P
    {
        get
        {
            return ElementNode(PTag);
        }
    }
                              
    public HtmlNode H3
    {
        get
        {
            return ElementNode(H3Tag);
        }
    }

    private HtmlNode ElementNode(string tag)
    {
        var result = nodes[index++];
        if (result.NodeType == HtmlNodeType.Text && string.IsNullOrWhiteSpace(result.InnerText))
            result = nodes[index++];
        Debug.Assert(result.NodeType == HtmlNodeType.Element);
        Debug.Assert(result.Name == tag);
        return result;
    }

    public HtmlNode Ul
    {
        get
        {
            return ElementNode(UlTag);
        }
    }

    public HtmlNode Next
    {
        get
        {
            var result = nodes[index++];
            return result;
        }
    }

    public HtmlNode Li
    {
        get
        {
            return ElementNode(LiTag);
        }
    }

    public HtmlNode Span
    {
        get
        {
            return ElementNode(SpanTag);
        }
    }

    public string Text
    {
        get
        {
            var result = nodes[index++];
            Debug.Assert(result.NodeType == HtmlNodeType.Text);
            return result.InnerText;
        }
    }

    public void AssertNoMore()
    {
        Debug.Assert(!HasMoreElements);
    }

    public HtmlNode H4(string innerText)
    {
        var result = ElementNode(H4Tag);
        Debug.Assert(result.InnerText == innerText);
        return result;
    }

    public HtmlNode Pre
    {
        get
        {
            return ElementNode(PreTag);
        }
    }

    public bool AtHRef
    {
        get { return HasMoreElements && nodes[index].Name == ATag; }
    }

    public HtmlNode HRef
    {
        get { return ElementNode(ATag); }
    }

    public bool HasMoreElements
    {
        get { return index < nodes.Count(n => n.NodeType == HtmlNodeType.Element); }
    }

    public bool HasMore
    {
        get { return index < nodes.Count; }
    }

    public bool AtDiv
    {
        get { return HasMore && nodes[index].Name == DivTag; }
    }

    public bool AtPre
    {
        get { return HasMore && nodes[index].Name == PreTag; }
    }

    public bool AtP
    {
        get { return HasMore && nodes[index].Name == PTag; }
    }

    public bool AtH2
    {
        get { return HasMore && nodes[index].Name == H2Tag; }
    }

    public bool AtH3
    {
        get { return HasMore && nodes[index].Name == H3Tag; }
    }

    public bool AtH3OfClass(string cls)
    {
        return HasMore && nodes[index].Name == H3Tag && nodes[index].OfClass(cls);
    }

    public bool AtText
    {
        get { return HasMore && nodes[index].NodeType == HtmlNodeType.Text; }
    }

    public void SkipWhiteSpace()
    {
        while (HasMore && AtText && string.IsNullOrWhiteSpace(nodes[index].InnerText))
        {
            index++;
        }
    }
}